/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logic;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.Documento;
import model.Palabra;
import model.Posteo;
import model.Valoracion;
import model.Vocabulario;
import persistence.SqlConnector;

/**
 *
 * @author
 */
public class Buscador {

    private String consulta;
    private LinkedList<String> terminos;
    private HashMap<String, Valoracion> valoracion;
    private Vocabulario voc = null;
    private int n; //cantidad total de documentos

    public Buscador(String consulta) {
        this.consulta = consulta;
        valoracion = new HashMap<String, Valoracion>();
        this.voc = Vocabulario.getInstance();
        System.out.println("Vocabulario tiene palabras: " + voc.getTerminos().size());
        try {
            n = getTotalDocs();
        } catch (Exception ex) {
            Logger.getLogger(Buscador.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private int getTotalDocs() throws Exception {
        SqlConnector connector = new SqlConnector();
        connector.connect();
        ResultSet result = connector.executeStatementQuery("SELECT count(*) as n FROM documento");
        result.next();
        int n= result.getInt("n");
        System.out.println(n);
        connector.disconnect();
        return n;
    }

    private void procesarConsulta() {
        String consultaLimpia = Utils.limpiarAcentos(consulta);
        terminos = Utils.separarPalabras(consultaLimpia);
    }

    public void setConsulta(String consulta) {
        this.consulta = consulta;
    }

    public String getConsulta() {
        return consulta;
    }

    public LinkedList<String> getTerminos() {
        return terminos;
    }

    public void setTerminos(LinkedList<String> terminos) {
        this.terminos = terminos;
    }

    public Valoracion[] buscar() throws Exception {
        procesarConsulta();
        SqlConnector connector = new SqlConnector();
        connector.connect();
        boolean debug = true;

        for (String termino : terminos) {

            Palabra palabra = voc.getPalabra(termino);
            if (palabra != null) {
                ArrayList<Posteo> posteoList = new ArrayList<Posteo>();
                try {

                    //Armar posteos (new Posteo()) de esa palabra con sus documentos.
                    Documento doc = null;                    
                    ResultSet result = connector.executeStatementQuery("SELECT * FROM posteos p, documento d  WHERE p.idDoc = d.id AND p.idTermino = " + palabra.getId());

                    while(result.next()){
//                        ResultSet resultDoc = connector.executeStatementQuery("SELECT * FROM documento d WHERE d.id = " + result.getInt("idDoc"));
//                        if(resultDoc.next()){
                            doc = new Documento(result.getInt("id"), result.getString("nombre"), result.getString("path"), result.getInt("cantPalabras"));
                        //}
                        posteoList.add(new Posteo(doc, result.getInt("tf")));
                    }

//                    //Recorrer posteos armados de esa palabra e ir armando los objetos Valoracion (new Valoracion())
                    for (Posteo posteo : posteoList) {
                        Valoracion val = valoracion.get(posteo.getDocumento().getNombre());
                         
//                        Valoracion val = valoracion.put(posteo.getDocumento().getNombre(), new Valoracion(posteo.getDocumento()));
                        
                        if (val != null) {
                            val.incrementarCantTerminosDeConsultaEnDoc(); //Revisar si con "val" afecto al mismo objeto que el anterior (en teoría si)
                        }
                        else
                            val = valoracion.put(posteo.getDocumento().getNombre(), new Valoracion(posteo.getDocumento()));

                        val = valoracion.get(posteo.getDocumento().getNombre());

//                        val.setValoracion(val.getValoracion() * val.getCantTerminosDeConsultaEnDoc() + (1 - (double) palabra.getCantDoc() / (double) posteo.getTf()));
//                       val.setValoracion(val.getValoracion() 
//                        + (double) (
//                                      (1 - 
//                                            (double) palabra.getCantDoc() /
//                                            (double) voc.getTerminos().size()
//                                          ) * (double) posteo.getTf()
//                                   ));

                        val.setValoracion(val.getValoracion() 
                        + (((double) 1 - (double) palabra.getCantDoc() / (double) n)
                                * (double) posteo.getTf()));

                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //Normalizar pesos - Comentado ya que no tengo los archivos en Disco y en tal caso Valoración pasará a valer "cualquier churro"

        for(Map.Entry<String,Valoracion> valor : valoracion.entrySet()){
            System.out.println("Antes: " + valor.getValue().getValoracion());
            valor.getValue().setValoracion(valor.getValue().getValoracion() * valor.getValue().getCantTerminosDeConsultaEnDoc() /
                    valor.getValue().getDocumento().getCantPalabras()); //getLongitud() debería devolver el tamaño del archivo en disco...
            System.out.println("Despues: " + valor.getValue().getValoracion());
        }
        
        //Valoracion[] valoracionArray = (Valoracion[]) valoracion.values().toArray(); //PORQUE NO FUNCA ASI?

        Collection<Valoracion> valoracionCollection = valoracion.values();
        Valoracion[] valoracionArray  = new Valoracion[valoracionCollection.size()];
        int i = 0;
        for (Valoracion val : valoracionCollection) {
            valoracionArray[i] = val;
            i++;
        }
        
        Ordenador ordenador = new Ordenador(valoracionArray);
        ordenador.ordenar();
        
        return valoracionArray;
    }


}



















///*
// * To change this template, choose Tools | Templates
// * and open the template in the editor.
// */
//package logic;
//
//import java.sql.ResultSet;
//import java.util.ArrayList;
//import java.util.Collection;
//import java.util.HashMap;
//import java.util.LinkedList;
//import java.util.Map;
//import java.util.logging.Level;
//import java.util.logging.Logger;
//import model.Documento;
//import model.Palabra;
//import model.Posteo;
//import model.Valoracion;
//import model.Vocabulario;
//import persistence.SqlConnector;
//
///**
// *
// * @author
// */
//public class Buscador {
//
//    private String consulta;
//    private LinkedList<String> terminos;
//    private HashMap<String, Valoracion> valoracion;
//    private Vocabulario voc = null;
//    private int n;//total de documentos
//
//    public Buscador(String consulta) {
//        this.consulta = consulta;
//        valoracion = new HashMap<String, Valoracion>();
//        this.voc = Vocabulario.getInstance();
//        System.out.println("Vocabulario tiene palabras: " + voc.getTerminos().size());
//        try {
//            n=getTotalDocs();
//        } catch (Exception ex) {
//            Logger.getLogger(Buscador.class.getName()).log(Level.SEVERE, null, ex);
//        }
//    }
//
//    private void procesarConsulta() {
//        String consultaLimpia = Utils.limpiarAcentos(consulta);
//        terminos = Utils.separarPalabras(consultaLimpia);
//    }
//
//    public void setConsulta(String consulta) {
//        this.consulta = consulta;
//    }
//
//    public String getConsulta() {
//        return consulta;
//    }
//
//    public LinkedList<String> getTerminos() {
//        return terminos;
//    }
//
//    public void setTerminos(LinkedList<String> terminos) {
//        this.terminos = terminos;
//    }
//
//    public Valoracion[] buscar() throws Exception {
//        procesarConsulta();
//        SqlConnector connector = new SqlConnector();
//        connector.connect();
//        boolean debug = true;
//        
//        for (String termino : terminos) { //FOR POR CADA TERMINO
//
//            Palabra palabra = voc.getPalabra(termino);//Obtenemos la palabra del vocabulario
//            if (palabra != null) {//Si la palabra existe
//                ArrayList<Posteo> posteoList = new ArrayList<Posteo>();
//                try {
//
//                    //Armar posteos (new Posteo()) de esa palabra con sus documentos.
//                    Documento doc = null;
//                    //obtenemos los 1º 100 posteos ordenados por tf
//                    ResultSet result = connector.executeStatementQuery("SELECT * FROM posteos p WHERE p.idTermino = " + palabra.getId());
////                    ResultSet result = connector.executeStatementQuery("SELECT * FROM posteos p WHERE p.idTermino = " + palabra.getId() + " order by tf desc limit 100");
//
//                    while (result.next()) { //por cada un de los 100 posteos
//                        ResultSet resultDoc = connector.executeStatementQuery("SELECT * FROM documento d WHERE d.id = " + result.getInt("idDoc"));
//                        if (resultDoc.next()) {
//                            doc = new Documento(resultDoc.getInt("id"), resultDoc.getString("nombre"), resultDoc.getString("path"), resultDoc.getInt("cantPalabras"));
//                        }
//                        posteoList.add(new Posteo(doc, result.getInt("tf"))); //tenemos una lista con los 100 primeros posteos
//                    }
//
//                    //Recorrer posteos armados de esa palabra e ir armando los objetos Valoracion (new Valoracion())
//                    for (Posteo posteo : posteoList) {//por cada uno de los 100 posteos
//                        Valoracion val = valoracion.put(posteo.getDocumento().getNombre(), new Valoracion(posteo.getDocumento()));
//                        if (val != null) {
//                            valoracion.get(posteo.getDocumento().getNombre()).incrementarCantTerminosDeConsultaEnDoc(); 
//                            System.out.println(posteo.getDocumento().getNombre() + " terminos de consulta en doc: " + valoracion.get(posteo.getDocumento().getNombre()).getCantTerminosDeConsultaEnDoc());
//                        }
//                        val = valoracion.get(posteo.getDocumento().getNombre());
//
//                        val.setValoracion(val.getValoracion() + (double) (1 - ((double) palabra.getCantDoc()
//                                / (double) voc.getTerminos().size()) * (double) posteo.getTf()));
//
//                    }
//
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//
//        //Normalizar pesos - Comentado ya que no tengo los archivos en Disco y en tal caso Valoración pasará a valer "cualquier churro"
//
//        for (Map.Entry<String, Valoracion> valor : valoracion.entrySet()) {
//            System.out.println("Antes: " + valor.getValue().getValoracion());
//            valor.getValue().setValoracion(valor.getValue().getValoracion() * valor.getValue().getCantTerminosDeConsultaEnDoc()
//                    / valor.getValue().getDocumento().getCantPalabras()); //getLongitud() debería devolver el tamaño del archivo en disco...
//            System.out.println("Despues: " + valor.getValue().getValoracion());
//        }
//
////        Valoracion[] valoracionArray = (Valoracion[]) valoracion.values().toArray(); PORQUE NO FUNCA ASI?
//
//        Collection<Valoracion> valoracionCollection = valoracion.values();
//        Valoracion[] valoracionArray = new Valoracion[valoracionCollection.size()];
//        int i = 0;
//        for (Valoracion val : valoracionCollection) {
//            valoracionArray[i] = val;
//            i++;
//        }
//
//        Ordenador ordenador = new Ordenador(valoracionArray);
//        ordenador.ordenar();
//
//        return valoracionArray;
//    }
//
//    private int getTotalDocs() throws Exception {
//        SqlConnector connector = new SqlConnector();
//        connector.connect();
//        ResultSet result = connector.executeStatementQuery("SELECT count(*) as n FROM documento");
//        result.next();
//        int n= result.getInt("n");
//        System.out.println(n);
//        connector.disconnect();
//        return n;
//
//    }
//}
